﻿#pragma once
#include "AppDelegate.h"
#include "WStringSupport.h"
#include "SceneMainMenu.h"
#include "SceneMusicSelect.h"
#include <thread>

#define random_r RandomHelper::random_real

USING_NS_CC;

Scene* SceneMainMenu::createScene()
{
	auto scene = Scene::create();
	auto layer = SceneMainMenu::create();
	layer->setAnchorPoint(Point(0.5, 0.5));
	scene->addChild(layer);
	return scene;
}

bool SceneMainMenu::init()
{
	if (!Layer::init())
	{
		return false;
	}
	addChild(LayerColor::create(Color4B::WHITE));

	playRandomBGM();
	createBG();
	//createMenu();

	scheduleUpdate();

	auto testlabel = Label::createWithTTF("Preview version.", FONTA, 32);
	UI::setNodeAnch(testlabel, ANCH_TL);
	testlabel->setPosition(0, frameSize.height);
	addChild(testlabel, 65535);

	auto uiss = UISceneSwitcher::create(UISS_MODE(sceneSwitchMode), ENTER);
	addChild(uiss);
	uiss->play();
	return true;
}

void SceneMainMenu::createBG()
{
	Sprite* bgimage;
	if (!pNotemgr->bgFile.empty()) bgimage = Sprite::create(pNotemgr->bgFile);
	else bgimage = Sprite::create();
	bgimage->setPosition(Vec2(frameSize.width / 2, frameSize.height / 2));
	auto zoom = 1.5;
	UI::setNodeFillInArea(bgimage, Size(frameSize.width*zoom, frameSize.height*zoom));
	bgimage->setOpacity(0);
	bgimage->runAction(Spawn::create(FadeIn::create(2.f), EaseSineInOut::create(ScaleBy::create(40.f, 1 / zoom)), NULL));
	addChild(bgimage);

	pBGBottom = MMBottomBar::create(frameSize.width*0.0625f);
	pBGBottom->setBgmInfo(pNotemgr->metaData.titleU, pNotemgr->metaData.artistU);
	addChild(pBGBottom, 200);

	auto pTitleBar = MMBottomBar::create(frameSize.width*0.0625f, true);
	pTitleBar->setBgmInfo("Infinity DreaMus", "Dev.SakuyA");
	pTitleBar->setPosition(0, frameSize.height - frameSize.width*0.0625f);
	addChild(pTitleBar);

	auto startBarL = LayerGradient::create(pUI->themeColorB(255), pUI->themeColorB(0), Vec2(-1, 0));
	startBarL->changeWidthAndHeight(frameSize.width, frameSize.height / 16);
	UI::setNodeAnch(startBarL, ANCH_MR);
	startBarL->setPosition(frameSize.width / 2, frameSize.height / 3);
	addChild(startBarL);
	auto startBarR = LayerGradient::create(pUI->themeColorB(255), pUI->themeColorB(0), Vec2(1, 0));
	startBarR->changeWidthAndHeight(frameSize.width, frameSize.height / 16);
	UI::setNodeAnch(startBarR, ANCH_ML);
	startBarR->setPosition(frameSize.width / 2, frameSize.height / 3);
	addChild(startBarR);

	startTextConfig.customGlyphs = NULL;
	startTextConfig.distanceFieldEnabled = false;
	startTextConfig.fontFilePath = FONTA;
	startTextConfig.fontSize = 48;
	startTextConfig.glyphs = GlyphCollection::DYNAMIC;
	startTextConfig.outlineSize = 0;
	pLabelStart = Label::createWithTTF(startTextConfig, "CLICK ANYWHERE TO START");
	pLabelStart->setTextColor(pUI->textColorB(255));
	pLabelStart->setPosition(Vec2(frameSize.width / 2, frameSize.height / 3));
	pLabelStart->setOpacity(64);
	addChild(pLabelStart, 10);

	auto mouseListener = EventListenerMouse::create();
	mouseListener->onMouseDown = CC_CALLBACK_0(SceneMainMenu::gotoMusicSelectScene, this);
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(mouseListener, this);

}

void SceneMainMenu::createMenu()
{
	float menuIcoWidth = pUI->dsnSize(128);
	int menuItemCount = 4;
	auto posx = frameSize.width / (menuItemCount + 1);
	auto posy = frameSize.height * 2 / 5;
	for (int i = 1; i <= menuItemCount; i++)
	{
		string iconFile = "";
		char* strEN = new char[64];
		function<void()> mouseDownAction;
		switch (i)
		{
			case 1:
				iconFile = "image/MainMenu/solo.png";
				strEN = "SINGLE";
				mouseDownAction = [&] { gotoMusicSelectScene(); };
				break;
			case 2:
				iconFile = "image/MainMenu/online.png";
				strEN = "ONLINE";
				break;
			case 3:
				iconFile = "image/MainMenu/setting.png";
				strEN = "SETTING";
				//mouseDownAction = CC_CALLBACK_0(SceneMainMenu::toggleSettingPanel, this);
				break;
			case 4:
				iconFile = "image/MainMenu/exit.png";
				strEN = "EXIT";
				mouseDownAction = []() { Director::getInstance()->end(); };
				break;
			default:
				strEN = "";
		}
		auto itemWidth = pUI->dsnSize(192);
		auto menuItem = MMBigButton::create(itemWidth, iconFile, strEN);
		UI::setNodeAnch(menuItem, ANCH_MB);
		menuItem->setPosition(posx*i, posy);
		//menuItem->additionalEventActions = *actions;
		menuItem->setAdditionalEventAction(EventHelper::MOUSEDOWN, mouseDownAction);
		menuItem->setTag(i * 10);
		addChild(menuItem);
		//menuItem->regMouseEvent();
		menuitems.push_back(menuItem);
	}
}

void SceneMainMenu::playRandomBGM()
{
	bool isBgmPlaying;
	pAudioSystem->curbgm.pChl->isPlaying(&isBgmPlaying);
	if (!isBgmPlaying)
	{
		pNotemgr = pDB->getRandomMusicNote();
		pAudioSystem->setMasterVolume(VOLUMEMASTER);
		string previewFile = pNotemgr->getPreviewFileName();
		if (!previewFile.empty())
			pAudioSystem->playBGMFadeIn(previewFile, 1000, VOLUMEMUSIC, pNotemgr->previewPoint);
		else
			pAudioSystem->stopBGM();
	}
	noteIters = new vector<NoteManager::Note>::const_iterator[pNotemgr->trackCount];
	setNextEffectIter();

	if (pBGBottom != nullptr) pBGBottom->setBgmInfo(pNotemgr->metaData.titleU, pNotemgr->metaData.artistU);
}

void SceneMainMenu::update(float dt)
{
	if (!pNotemgr->musicFile.empty()) squareEffect();
}

void SceneMainMenu::gotoMusicSelectScene()
{
	sceneSwitchMode = random(0, 3);
	auto uiss = UISceneSwitcher::create(UISS_MODE(sceneSwitchMode), LEAVE);
	addChild(uiss);
	uiss->play();
	runAction(
		Sequence::create(
			DelayTime::create(1.5f),
			CallFunc::create([&]
	{
		Director* director = Director::getInstance();
		pSceneMusicSelect = SceneMusicSelect::createScene();
		director->replaceScene(pSceneMusicSelect);
	}),
			NULL
		)
	);

}

//void SceneMainMenu::toggleSettingPanel()
//{
//	if (isSettingOpen)
//	{
//		for (auto mi : menuitems)
//		{
//			mi->runAction(EaseExponentialOut::create(MoveBy::create(.33f, Vec2(0, -frameSize.height))));
//		}
//		pSettingPanel->runAction(EaseExponentialOut::create(MoveBy::create(.33f, Vec2(0, -frameSize.height))));
//		UI::setEventFlagByBit(1);
//		isSettingOpen = false;
//	}
//	else
//	{
//		if (!pSettingPanel)
//		{
//			pSettingPanel = UISetting::create(UI::getEventFlag() << 1);
//			pSettingPanel->setPosition(0, -frameSize.height);
//			addChild(pSettingPanel, 100);
//			pSettingPanel->setAdditionalEventAction(EventHelper::MOUSEDOWN, CC_CALLBACK_0(SceneMainMenu::toggleSettingPanel, this));
//		}
//		for (auto mi : menuitems)
//		{
//			mi->runAction(EaseExponentialOut::create(MoveBy::create(.33f, Vec2(0, frameSize.height))));
//		}
//		pSettingPanel->runAction(EaseExponentialOut::create(MoveBy::create(.33f, Vec2(0, frameSize.height))));
//		UI::moveEventFlagUp();
//		isSettingOpen = true;
//	}
//}

void SceneMainMenu::squareEffect()
{
	if (pAudioSystem->getBgmPosition() < curtime)
	{
		setNextEffectTime();
		setNextEffectIter();
	}
	curtime = pAudioSystem->getBgmPosition();
	if (curtime >= nextEffectTime)
	{
		auto startTextEffect = Label::createWithTTF(startTextConfig, "CLICK ANYWHERE TO START");
		startTextEffect->setTextColor(pUI->textColorB(255));
		startTextEffect->setPosition(pLabelStart->getPosition());
		startTextEffect->setOpacity(0);
		addChild(startTextEffect, 11);
		startTextEffect->runAction(
			Sequence::create(
				FadeTo::create(0.05f, 64),
				TintTo::create(0.05f, pUI->themeColor3B()),
				Spawn::create(
					FadeTo::create(0.15f, 0),
					ScaleTo::create(0.15f, 1.2f),
					NULL
				),
				RemoveSelf::create(),
				NULL
			)
		);
		if (timeSegIndex < (pNotemgr->timingSegsSize - 1)
			&& (nextEffectTime >= (unsigned int)pNotemgr->timingSegs[timeSegIndex + 1].startTime))
		{
			timeSegIndex++;
		}
		nextEffectTime += pNotemgr->timingSegs[timeSegIndex].mspb;
	}
	float fadeoutdura = .33f;
	for (int i = 0; i < pNotemgr->trackCount; i++)
	{
		if (noteIters[i] != pNotemgr->trackNotes[i].cend())
			if ((unsigned int)noteIters[i]->startTime <= curtime)
			{
				//auto ps = pBGSquare[random(0, 9)][random(0, 4)];
				int psdiv = random(20, 40);
				auto ps = LayerColor::create(Color4B::WHITE, frameSize.width / psdiv, frameSize.width / psdiv);
				ps->setRotation(random(0, 45));
				ps->setOpacity(0);
				ps->setPositionX(random(frameSize.width*.1f + i* frameSize.width*.8f / pNotemgr->trackCount,
										frameSize.width*.1f + (i + 1)* frameSize.width*.8f / pNotemgr->trackCount));
				ps->setPositionY(random(frameSize.height*.1f, frameSize.height*.9f));
				auto psin = LayerColor::create(Color4B::WHITE, frameSize.width / psdiv, frameSize.width / psdiv);
				psin->setScale(.95f);
				psin->setOpacity(0);
				ps->addChild(psin);
				addChild(ps);
				//if (ps->getNumberOfRunningActions() == 0)
				//{
				if (noteIters[i]->noteType == noteIters[i]->SINGLE)
				{
					/*
					ps->runAction(
						Sequence::create(
							Spawn::create(
								FadeTo::create(0.05f, 30),
								ScaleTo::create(0.05f, 1.05f),
								NULL
							),
							Spawn::create(
								FadeTo::create(0.5f, random(10, 20)),
								ScaleTo::create(0.5f, 1),
								NULL
							),
							NULL
						)
					);
					*/
					auto act = Sequence::create(
						FadeTo::create(.05f, 224),
						Spawn::create(
							RotateBy::create(fadeoutdura, -45),
							FadeTo::create(fadeoutdura, 0),
							ScaleBy::create(.5f, 1.5f),
							NULL
						),
						RemoveSelf::create(),
						NULL
					);
					ps->runAction(act);
					psin->runAction(act->clone());
				}
				else if (noteIters[i]->noteType == noteIters[i]->LONG)
				{
					ps->setScale(1.75);
					float duration = (noteIters[i]->endTime - noteIters[i]->startTime) / 1000.f;
					auto act = Sequence::create(
						FadeTo::create(.05f, 224),
						RotateBy::create(duration, -45 * duration / fadeoutdura),
						Spawn::create(
							RotateBy::create(fadeoutdura, -45),
							FadeTo::create(fadeoutdura, 0),
							ScaleBy::create(.5f, 1.5f),
							NULL
						),
						RemoveSelf::create(),
						NULL
					);
					ps->runAction(act);
					psin->runAction(act->clone());
				}
			//}
				noteIters[i]++;
			}
	}
}

void SceneMainMenu::setNextEffectTime()
{
	nextEffectTime = pNotemgr->timingSegs[0].startTime;
	unsigned int bgmPos = pAudioSystem->getBgmPosition();
	timeSegIndex = 0;
	for (; nextEffectTime < bgmPos; nextEffectTime += pNotemgr->timingSegs[timeSegIndex].mspb)
	{
		if (timeSegIndex < (pNotemgr->timingSegsSize - 1)
			&& (nextEffectTime >= (unsigned int)pNotemgr->timingSegs[timeSegIndex + 1].startTime))
		{
			timeSegIndex++;
		}
	}
}

void SceneMainMenu::setNextEffectIter()
{
	if (!pNotemgr->musicFile.empty())
	{
		for (int i = 0; i < pNotemgr->trackCount; i++)
		{
			noteIters[i] = pNotemgr->trackNotes[i].cbegin();
			for (; (unsigned int)noteIters[i]->startTime < pAudioSystem->getBgmPosition(); noteIters[i]++) {}
		}
	}
}